package com.ybkj.daijia.server.service.impl;

import com.ybkj.daijia.api.beatpay.utils.AES256;
import com.ybkj.daijia.api.beatpay.utils.BestPayError;
import com.ybkj.daijia.api.beatpay.utils.BestPayErrorMap;
import com.ybkj.daijia.api.beatpay.utils.CryptTool;
import com.ybkj.daijia.api.beatpay.utils.HttpRequestUtils;
import com.ybkj.daijia.api.beatpay.utils.RSA;
import com.ybkj.daijia.api.beatpay.utils.SysConstants;
import com.ybkj.daijia.server.service.BestPayService;
import javax.servlet.http.HttpServletRequest;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 翼支付服务层接口实现类
 *
 * @author zane
 */
public class BestPayServiceImpl implements BestPayService {

    private static Logger logger = LoggerFactory.getLogger(BestPayServiceImpl.class);

//	@Autowired
//	private SettingUtils settingUtil;


    public BestPayError createOrder() throws Exception {

        /***********************************************************************
         *
         * 开始下订单
         *
         ***********************************************************************/

        // 获取系统配置
        // Setting setting= settingUtil.get();

        // 获取生产环境地址
        String createEnvUrl = "";
        logger.info("生产环境URL：" + createEnvUrl);

        // 获取商户信息
        String merchantId = ""; // setting.getxxx // 商户id
        String merKey = ""; // setting.getxxx // 商户key

        // 获取用户信息
        String customerId = ""; // 用户手机号，必填参数，否则支付失败
        logger.info("用户手机号：" + customerId);

        //下单MAC
        StringBuilder sb = new StringBuilder();
        sb.append("MERCHANTID=").append(merchantId);
        sb.append("&ORDERSEQ=").append("");
        sb.append("&ORDERREQTRANSEQ=").append("");
        sb.append("&ORDERREQTIME=").append("");
        sb.append("&KEY=").append(merKey);

        // 计算mac
        logger.info("MAC(MD5)--before--String：" + sb.toString());
        String mac = CryptTool.md5Digest(sb.toString());
        logger.info("MAC(MD5)--after--String:" + mac);

        //下单请求参数
        StringBuilder perpareSignParam = new StringBuilder();
        perpareSignParam.append("MERCHANTID=").append(merchantId)
            .append("&SUBMERCHANTID=").append("")
            .append("&ORDERSEQ=").append("") // 订单id
            .append("&ORDERREQTRANSEQ=").append("") // 订单流水号
            .append("&ORDERREQTIME=").append("") // 下单时间
            .append("&TRANSCODE=").append("01") //
            .append("&ORDERAMT=").append("") // 下单金额单位分，支付金额单位元
            .append("&ORDERCCY=").append("RMB") // 人民币
            .append("&SERVICECODE=").append("05") // 固定值
            .append("&PRODUCTID=").append("") // 业务标识代码
            .append("&PRODUCTDESC=").append("") // 商品描述-给网关下单使用
            .append("&LOGINNO=").append("")
            .append("&PROVINCECODE=").append("")
            .append("&CITYCODE=").append("")
            .append("&DIVDETAILS=").append("")
            .append("&ENCODETYPE=").append("1")
            .append("&MAC=").append(mac)
            .append("&ATTACH=").append("")
            .append("&requestSystem=").append("1");
        String requestBody = perpareSignParam.toString();
        logger.info("requestBody:" + requestBody);

        // 调用接口进行下单,获取下单结果
//        HttpPost httpPost = new HttpPost(createEnvUrl);
//        httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
//        StringEntity se = new StringEntity(requestBody, "UTF-8");
//        httpPost.setEntity(se);
//        HttpResponse httpResponse = HttpClients.createDefault().execute(httpPost);
//        String responseStr = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
        String responseBody = "";
        logger.info("responseBody:" + responseBody);

        // 下单请求失败
        if (null == responseBody
            || responseBody.isEmpty()
            || !responseBody.contains("&")) {
            BestPayError error = BestPayErrorMap.ERROR_CREATE_ORDER_EXCEPTION;
            logger.info("create order faild:" + error.getErrorMsg());
            return error;
        }

        // 请求成功，获取返回数据(返回的是"code&msg"的这种格式，我们要来解析他)
        String[] result = responseBody.split("&");
        String code = result[0];
        String codeMsg = result[1];

        // 看是否下单成功
        if (!code.equals("00")) {
            BestPayError error = BestPayErrorMap.ERROR_CREATE_ORDER_EXCEPTION;
            logger.info("create order faild:" + codeMsg);
            return error;
        }

        /***********************************************************************
         *
         * 开始获取publicKey
         *
         ***********************************************************************/

        // 下单成功，调用接口获取公钥
        String publicKeyURL = "";
        JSONObject params = new JSONObject();
        params.put("keyIndex", ""); // 空值
        params.put("encryKey", ""); // 空值
        params.put("encryStr", ""); // 空值
        params.put("interCode", "INTER.SYSTEM.001"); // 固定值

        // 开始获取公钥
        String publicKeyResult = HttpRequestUtils.doPost(publicKeyURL, params.toString());

        // 请求失败
        if (null == publicKeyResult || publicKeyResult.isEmpty()) {
            BestPayError error = BestPayErrorMap.ERROR_GET_PUBLIC_KEY_EXCEPTION;
            logger.info("get public key faild:" + error.getErrorMsg());
            return error;
        }

        // 获取失败
        JSONObject keyResult = new JSONObject(publicKeyResult);
        Boolean success = keyResult.getBoolean("success");
        if (!success) {
            String errorMsg = keyResult.getString("errorMsg");
            BestPayError error = BestPayErrorMap.ERROR_GET_PUBLIC_KEY_EXCEPTION;
            logger.info("get public key faild:" + errorMsg);
            return error;
        }

        // 获取成功，获取响应数据
        JSONObject keyResult_ = keyResult.getJSONObject("result");
//        String aesRandomId = keyResult_.getString("aesRandomId");
        String keyIndex = keyResult_.getString("keyIndex");
        String pubKey = keyResult_.getString("pubKey");
//        String sessionId = keyResult_.getString("sessionId");
//        String waitTime = keyResult_.getString("waitTime");

        /***********************************************************************
         *
         * 开始通过订单数据，publicKey唤起H5收银台
         *
         ***********************************************************************/

        //生成数字签名
        StringBuilder md5Builder = new StringBuilder();
        md5Builder.append("SERVICE=").append("mobile.securitypay.pay")
            .append("&MERCHANTID=").append(merchantId)
            .append("&MERCHANTPWD=").append("")
            .append("&SUBMERCHANTID=").append("")
            .append("&BACKMERCHANTURL=").append("")
            .append("&ORDERSEQ=").append("")
            .append("&ORDERREQTRANSEQ=").append("")
            .append("&ORDERTIME=").append("")
            .append("&ORDERVALIDITYTIME=").append("")
            .append("&CURTYPE=").append("RMB")
            .append("&ORDERAMOUNT=").append("")
            .append("&SUBJECT=").append("")
            .append("&PRODUCTID=").append("")
            .append("&PRODUCTDESC=").append("")
            .append("&CUSTOMERID=").append(customerId)
            .append("&SWTICHACC=").append("")
            .append("&KEY=").append(merKey);

        logger.info("签名前原串：" + md5Builder.toString());
        String sign = CryptTool.md5Digest(md5Builder.toString());
        logger.info("签名后密文串：" + sign);

        //拼接请求报文
        final String paramStr = "MERCHANTID=" + merchantId
            + "&SUBMERCHANTID=" + ""
            + "&MERCHANTPWD=" + ""
            + "&ORDERSEQ=" + ""
            + "&ORDERAMOUNT=" + ""
            + "&ORDERTIME=" + ""
            + "&ORDERVALIDITYTIME=" + ""
            + "&PRODUCTDESC=" + ""
            + "&CUSTOMERID=" + customerId
            + "&PRODUCTAMOUNT=" + ""
            + "&ATTACHAMOUNT=" + ""
            + "&CURTYPE=" + "RMB"
            + "&BEFOREMERCHANTURL=" + ""
            + "&BACKMERCHANTURL=" + ""
            + "&ATTACH=" + ""
            + "&PRODUCTID=" + ""
            + "&USERIP=" + ""
            + "&DIVDETAILS=" + ""
            + "&ACCOUNTID=" + ""
            + "&BUSITYPE=" + ""
            + "&ORDERREQTRANSEQ=" + ""
            + "&SERVICE=" + "mobile.securitypay.pay"
            + "&SIGNTYPE=" + "MD5"
            + "&SIGN=" + sign
            + "&SUBJECT=" + ""
            + "&ORDERAMOUNT=" + ""
            + "&SWTICHACC=" + ""
            + "&USERLANGUAGE=" + ""
            //不需要免登功能，下面三个参数可以不填
            //+ "&tid=" + accountid
            //+ "&key_index=" + keyIndex
            //+ "&key_tid=" + token
            ;
        logger.info("请求报文:" + paramStr);

        // 进行RSA+AES256加密，拼凑URL
        String key = AES256.getStringRandom(32);
        String encryStr = AES256.AES_Encode(paramStr, key);
        key = RSA.encrypt(key, pubKey, SysConstants.SYS_CHARSET);
        String webUrl = createEnvUrl
            + "/gateway.pay"
            + "?platform=wap_3.0"
            + "&encryStr=" + encryStr
            + "&keyIndex=" + keyIndex
            + "&encryKey=" + key
            .replaceAll("\\+", "%2B");
        logger.info("唤起H5收银台的url：" + webUrl);
        BestPayError error = BestPayErrorMap.ERROR_OK;
        error.setWebUrl(webUrl);
        return error;
    }

    /**
     * 翼支付H5支付回调
     *
     * @param request
     * @throws Exception
     */
    public void bestPayH5callBack(HttpServletRequest request) throws Exception {
        // 获取回调数据
        String UPTRANSEQ = request.getParameter("UPTRANSEQ");
        String MERCHANTID = request.getParameter("MERCHANTID");
        String TRANDATE = request.getParameter("TRANDATE");
        String RETNCODE = request.getParameter("RETNCODE");
        String RETNINFO = request.getParameter("RETNINFO");
        String ORDERREQTRANSEQ = request.getParameter("ORDERREQTRANSEQ");
        String ORDERSEQ = request.getParameter("ORDERSEQ");
        String ORDERAMOUNT = request.getParameter("ORDERAMOUNT");
        String PRODUCTAMOUNT = request.getParameter("PRODUCTAMOUNT");
        String ATTACHAMOUNT = request.getParameter("ATTACHAMOUNT");
        String CURTYPE = request.getParameter("CURTYPE");
        String ENCODETYPE = request.getParameter("ENCODETYPE");
        String BANKID = request.getParameter("BANKID");
        String ATTACH = request.getParameter("ATTACH");
        String UPREQTRANSEQ = request.getParameter("UPREQTRANSEQ");
        String UPBANKTRANSEQ = request.getParameter("UPBANKTRANSEQ");
        String PRODUCTNO = request.getParameter("PRODUCTNO");
        String SIGN = request.getParameter("SIGN");

        // 验证签名
        String key = "";
        String signStr = "UPTRANSEQ=" + UPTRANSEQ
            + "&MERCHANTID=" + MERCHANTID
            + "&ORDERSEQ=" + ORDERSEQ
            + "&ORDERAMOUNT=" + ORDERAMOUNT
            + "&RETNCODE=" + RETNCODE
            + "&RETNINFO=" + RETNINFO
            + "&TRANDATE=" + TRANDATE
            + "&KEY=" + key;
        String localSign = CryptTool.md5Digest(signStr);

        // 验签失败
        if (!localSign.equals(SIGN)) {
            logger.info("支付回调，验签失败！");
            return;
        }

        // 验签成功，看是否支付成功("0000为成功，其他均为失败")
        if (RETNCODE.equals("0000")) {
            // 更新支付状态
        } else {
            // 不作处理
        }
    }

}
